package xj.toolkit.redis.single;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.Pool;
import xj.toolkit.redis.RedisPoolStaticticsMBean;

public class Jedis2Pool extends Pool<Jedis2> {

//	public void returnResource(final Jedis2 resource) {
//		if (resource != null) {
//			this.returnResourceObject(resource);
//		}
//	}
//
//	protected void returnBrokenResource(Jedis2 resource) {
//		if (resource == null) {
//			return;
//		}
//
//		try {
//			internalPool.invalidateObject(resource);
//		} catch (Exception e) {
//			throw new JedisException("Could not return the broken resource to the pool", e);
//		}
//	}

	public Jedis2 getResource() {
		Jedis2 jedis2 = super.getResource();
		jedis2.setDataSource(this);
		return jedis2;
	}

	private static class Jedis2Factory extends BasePooledObjectFactory<Jedis2> {

		private final String host;
		private final int port;
		private final int timeout;
		private final String password;

		public Jedis2 create() throws Exception {
			Jedis2 jedis = null;
			if (timeout > 0) {
				jedis = new Jedis2(host, port, timeout);
			} else {
				jedis = new Jedis2(host, port);
			}
			jedis.connect();
			if (null != password && password.trim().length() > 0) {
				jedis.auth(password);
			}
			return jedis;
		}

		public PooledObject<Jedis2> wrap(Jedis2 obj) {
			return new DefaultPooledObject<Jedis2>(obj);
		}

		public void destroyObject(PooledObject<Jedis2> obj) throws Exception {
			Jedis2 jedis = obj.getObject();
			if (jedis.isConnected()) {
				try {
					try {
						jedis.quit();
					} catch (Exception e) {
					}
					jedis.disconnect();
				} catch (Exception e) {
				}
			}
		}

		public boolean validateObject(PooledObject<Jedis2> obj) {
			final Jedis jedis = obj.getObject();
			try {
				return jedis.isConnected() && jedis.ping().equals("PONG");
			} catch (final Exception e) {
				return false;
			}

		}

		public Jedis2Factory(String host, int port, int timeout, String password) {
			this.host = host;
			this.port = port;
			this.timeout = timeout <= 0 ? -1 : timeout;
			this.password = password;
		}
	}

	public Jedis2Pool(GenericObjectPoolConfig poolConfig, String host) {
		this(poolConfig, host, 6379, 2000, null);
	}

	public Jedis2Pool(String host) {

	}

	public Jedis2Pool(String host, int port) {
		super(new GenericObjectPoolConfig(), new Jedis2Factory(host, port, 2000, null));
	}

	public Jedis2Pool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password) {
		super(poolConfig, new Jedis2Factory(host, port, timeout, password));
	}

	public Jedis2Pool(GenericObjectPoolConfig poolConfig, String host, int port) {
		this(poolConfig, host, port, 2000, null);
	}

	public Jedis2Pool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout) {
		this(poolConfig, host, port, timeout, null);
	}

	public RedisPoolStaticticsMBean getRedisPoolStatictics() {
		return new RedisPoolStaticticsMBean(this.internalPool);
	}
}
